/**
 * $Id: ApplicationScopeLoader.java 19 2011-06-11 04:06:06Z feigme $
 */
package com.iary.interfaces.taglib;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.support.WebApplicationObjectSupport;

public class ApplicationScopeLoader extends WebApplicationObjectSupport {
	private static final Logger logger = LoggerFactory
			.getLogger(ApplicationScopeLoader.class);

	/** constant classes which can be injected by spring */
	private Map<String, String> constantClass;

	protected void initApplicationContext() {
		try {
			// build constants and put it to the application scope
			this.buildConstants();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * build constants map
	 * 
	 * @return constants map
	 * @throws ClassNotFoundException
	 */
	private void buildConstants() throws ClassNotFoundException {
		Map<String, Object> result = new HashMap<String, Object>();
		for (Map.Entry<String, String> map : constantClass.entrySet()) {
			// the constant group name
			String k = map.getKey();
			// the class
			String v = map.getValue();
			Class<?> clazz = this.getClass().getClassLoader().loadClass(v);
			Field[] fields = clazz.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				int modifier = field.getModifiers();
				// must be final & public
				if (Modifier.isFinal(modifier) && !Modifier.isPrivate(modifier))
					try {
						String name = field.getName();
						Object value = field.get(this);
						logger.debug("building constants{}: name={},value={}",
								new Object[] { k, name, value });
						result.put(name, value);
					} catch (IllegalAccessException e) {
					}
			}

			logger.info("put constant [{}] to application scope.", k);
			this.getServletContext().setAttribute(k, result);
		}
	}

	public Map<String, String> getConstantClass() {
		return constantClass;
	}

	public void setConstantClass(Map<String, String> constantClass) {
		this.constantClass = constantClass;
	}
}
